# from typing import List, Dict, Any
#
# from langchain_core.tools import BaseTool
# from langchain_openai import ChatOpenAI
#
# from app.configs.settings import api_settings, config as app_config
# from app.core.tools.weather_tool import get_current_weather
#
# EXTERNAL_TOOL_REGISTRY: Dict[str, BaseTool] = {
#     "get_current_weather": get_current_weather,
# }
#
#
# def create_llm_instance(llm_config: Dict[str, Any] = None) -> ChatOpenAI:
#     # llm_config is now optional and defaults to None
#     user_config = llm_config or {}
#     config = {
#         "model": app_config.llm.name,
#         "temperature": app_config.llm.temperature,
#         **user_config,
#     }
#     return ChatOpenAI(
#         model=config["model"],
#         temperature=config["temperature"],
#         api_key=api_settings.OPENAI_API_KEY,
#         base_url=api_settings.OPENAI_BASE_URL
#     )
#
#
# def get_tools(tool_names: List[str]) -> List[BaseTool]:
#     if tool_names:
#         return [
#             EXTERNAL_TOOL_REGISTRY[name]
#             for name in tool_names
#             if name in EXTERNAL_TOOL_REGISTRY
#         ]
#     else:
#         return []

#============================================================================

from typing import List, Dict, Any, Optional
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_core.tools import BaseTool
from langchain_openai import ChatOpenAI

from app.configs.settings import api_settings, config as app_config
from app.core.tools.weather_tool import get_current_weather

EXTERNAL_TOOL_REGISTRY: Dict[str, BaseTool] = {
    "get_current_weather": get_current_weather,
}


def create_llm_instance(llm_config: Dict[str, Any] = None) -> ChatOpenAI:
    user_config = llm_config or {}
    config = {
        "model": app_config.llm.name,
        "temperature": app_config.llm.temperature,
        **user_config,
    }
    return ChatOpenAI(
        model=config["model"],
        temperature=config["temperature"],
        api_key=api_settings.OPENAI_API_KEY,
        base_url=api_settings.OPENAI_BASE_URL
    )


def get_tools(tool_names: List[str]) -> List[BaseTool]:
    if tool_names:
        return [
            EXTERNAL_TOOL_REGISTRY[name]
            for name in tool_names
            if name in EXTERNAL_TOOL_REGISTRY
        ]
    else:
        return []


def get_interview_chain(job_position: Any, persona: str) -> LLMChain:
    llm = create_llm_instance()

    prompt = PromptTemplate(
        input_variables=["job_description", "user_input", "chat_history"],
        template=f"""
        ### 角色设定 ###
        {persona}

        ### 岗位描述 ###
        {{job_description}}

        ### 历史对话 ###
        {{chat_history}}

        ### 候选人回答 ###
        {{user_input}}

        ### 你的任务 ###
        候选人选择的岗位是个人意向，你可以根据自己的判断给出更适合的岗位的推荐。
        请根据对话历史和候选人回答，提出一个自然、连贯的追问问题。
        问题应该符合你的角色设定，并有助于评估候选人的能力和经验。
        一般一次面试包含6-7轮对话。
        如果候选人的回答情况较好，你可以增加1-2轮对话。
        如果候选人的回答情况较差，你可以减少对话轮数，甚至结束面试。
        候选人在前3轮左右对话，可能是基本的信息交换、自我介绍或闲聊，这是了解阶段。
        了解阶段结束后，应该进入技术阶段，在技术阶段你应该提出一些岗位相关的技术问题。
        技术阶段中，如果发生候选人对话内容偏离面试的情况，第一次提醒，第二次直接结束面试。
        在面试的第6轮，必须提出一道与岗位相关的代码题（Python或Java），要求：
        1. 明确指定编程语言
        2. 清晰描述功能需求
        3. 提供具体的测试用例（使用【测试用例】标记）
        4. 代码题难度应与岗位要求匹配

        收到候选人的代码后，要先评估代码的语法正确性、功能完整性和代码规范性，
        给出具体的评估结果和改进建议，然后继续进行后续面试并不再提出代码题。
        """
    )

    chain = LLMChain(
        llm=llm,
        prompt=prompt,
        verbose=True
    )
    return chain